package com.warf.warftool;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map.Entry;
import java.util.Properties;

import org.apache.commons.io.monitor.FileAlterationListener;
import org.apache.commons.io.monitor.FileAlterationListenerAdaptor;
import org.apache.commons.io.monitor.FileAlterationMonitor;
import org.apache.commons.io.monitor.FileAlterationObserver;

import com.warf.warftool.utils.WarfUtils;
import com.warf.warftool.was.WasDeploy;

public class WarfDeployMain {

	/**
	 * @param args
	 */
	private long pollingInterval = 5 * 1000;
	private FileAlterationMonitor warfMonitor;
	private static HashMap<String, String> monitorQueue= new HashMap<String, String>();
	private static List<String> runningQueue= new ArrayList<String>();
	private Properties warfProperties;
	public WarfDeployMain(){
		String interval=WarfUtils.getPropertyValue(WarfUtils.PROP_BASE_NAME+".file.monitor.polling");
		if(interval != null){
			if( !interval.equalsIgnoreCase("")){
				pollingInterval= Long.parseLong(interval);
			}
		}
		warfMonitor = new  FileAlterationMonitor(pollingInterval);
	}
	
	
	
	public void setWarfProperties(Properties props){
		this.warfProperties=props;
	}
	public void addMonitorQueue(String appName, String path){
		if(path != null && appName != null){
			if(!path.equalsIgnoreCase("") && !appName.equalsIgnoreCase("")){
				if(!monitorQueue.containsKey(appName)){
					monitorQueue.put(appName, path);
				}
			}
		}
	}
	
	public void startMonitor(){
		if(warfMonitor != null){
			try {
				warfMonitor.start();
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}else{
			System.err.println("Direcotry Monitor is Null");
		}
	}
	
	public void deployFile(String appName, String fileName){
		System.out.println("AppName: "+appName+" FileName: "+fileName);
		boolean validFile=false;
		String earfilesString=warfProperties.getProperty(WarfUtils.PROP_ROOT_NAME+"."+appName+".ear.files");
		if(earfilesString != null){
			if(earfilesString.contains(fileName)){
				validFile=true;
				System.out.println("AppName: "+appName+" FileName: "+fileName+ " is Valid File for Deployment");
			}
		}
		
		String warfilesString=warfProperties.getProperty(WarfUtils.PROP_ROOT_NAME+"."+appName+".war.files");
		if(warfilesString != null){
			if(warfilesString.contains(fileName)){
				validFile=true;
				System.out.println("AppName: "+appName+" FileName: "+fileName+ " is Valid File for Deployment");
			}
		}
		if(validFile){
			if(!runningQueue.contains(appName)){
				runningQueue.add(appName);
				WasDeploy wasdeploy= new WasDeploy(appName,fileName);
				wasdeploy.run();
				runningQueue.remove(appName);
			}else{
				System.out.println("*****Task from AppName: "+appName+" already Running..");
			}
			
		}else{
			System.out.println("AppName: "+appName+" FileName: "+fileName+ " is Valid for Deployment. Please add the file to WarfConfig.properties");
		}
				
	}
	
	private boolean isCompletelyWritten(File file) {
	    RandomAccessFile stream = null;
	    try {
	        stream = new RandomAccessFile(file, "rw");
	        return true;
	    } catch (Exception e) {
	    	System.out.println("Skipping file " + file.getName() + " for this iteration due it's not completely written");
	    } finally {
	        if (stream != null) {
	            try {
	                stream.close();
	            } catch (IOException e) {
	            	System.err.println("Exception during closing file " + file.getName());
	            }
	        }
	    }
	    return false;
	}
	public void addFileMonitorListener(FileAlterationObserver observer ){
		 FileAlterationListener listener = new FileAlterationListenerAdaptor() {
			  @Override
	            public void onFileCreate(File file) {
	                try {
	                    // "file" is the reference to the newly created file
	                    System.out.println("File Created: "+ file.getCanonicalPath());
	                    if(monitorQueue.containsValue(file.getParent())){
	                    	 for (Entry<String, String> entry : monitorQueue.entrySet()) {
	                    		 if (entry.getValue().equals(file.getParent())) {
	                    			 String applicationName=entry.getKey();
	                    			 String fileName=file.getName();
	                    			 if(isCompletelyWritten(file)){
	                    				 deployFile(applicationName,fileName);
	                    			 }
	                    			 
	                    		 }

	                    	 }
	                    }
	                } catch (IOException e) {
	                    e.printStackTrace(System.err);
	                }
	            }
			  public void onFileChange(File file) {
				 try {
					System.out.println("File Changed: "+ file.getCanonicalPath());
					onFileCreate(file);
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				  
			  }
		 };
		 observer.addListener(listener);
		 warfMonitor.addObserver(observer);


	}
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		
		Properties prop = new Properties();
		try {
			prop.load(WarfDeployMain.class.getClassLoader().getResourceAsStream(WarfUtils.WARF_PROPERTIES_FILE));
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			System.exit(0);
		} catch (IOException e) {
			e.printStackTrace();
			System.exit(0);

		}
		WarfDeployMain warfDeploy= new WarfDeployMain();	
		warfDeploy.setWarfProperties(prop);
		
		String appNameString=prop.getProperty(WarfUtils.PROP_ROOT_NAME+".appName");
		if(appNameString == null){
			System.err.println("Application Name in "+WarfUtils.WARF_PROPERTIES_FILE+" is NULL. Please define alteast an empty:  "+WarfUtils.PROP_ROOT_NAME+".appName");
			System.exit(0);
		}
		List<String> applicationNames=WarfUtils.getAsArray(appNameString, ",");
		System.out.println("Application Name: "+applicationNames.toString());
		
		for(String appName: applicationNames){
			//WasDeploy wasdeploy= new WasDeploy(appName);
			//wasdeploy.run();
			String earPath= WarfUtils.getPropertyBaseRoot(appName,"ear.path");
			if(earPath != null){
				if(!earPath.equalsIgnoreCase("")){
					File folder = new File(earPath);
					if (folder.exists()) {
						System.out.println("Application Name: "+appName+"  Folder exist "+earPath+" Monitoring....");
						FileAlterationObserver observer = new FileAlterationObserver(folder);
						warfDeploy.addFileMonitorListener(observer);
						System.out.println("Application Path: "+folder.getAbsolutePath());
						warfDeploy.addMonitorQueue(appName, folder.getAbsolutePath());
						
					}else{
						System.out.println("Application Name: "+appName+"  :Folder does't exist "+earPath);
					}

				}
			}
		}
		warfDeploy.startMonitor();
		
	}
	

}
